#include "render.hh"
#include "gl.hh"

namespace gl
{
	namespace render
	{
		void text(std::string const& str, float spacing, float line_height)
		{
			gl::push_matrix();
			gl::push_matrix();
			for (auto ch: str){
				switch (ch){
					case '\t': // TODO: do the real job as tab does
						gl::translatef(4*spacing, 0, 0);
						break;
					case '\n':
						gl::pop_matrix();
						gl::translatef(0, -line_height, 0);
						gl::push_matrix();
						break;
					default:	// "default" here intentionally
						text(ch);
						// no "break" intentionally
					case ' ':
						gl::translatef(spacing, 0, 0);
				}
			}
			gl::pop_matrix();
			gl::pop_matrix();
		}

		void text(char ch)
		{
			switch (ch){
				// alpha
				case 'A':
				case 'a':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, +0.0);
					gl::end();
					break;
				case 'B':
				case 'b':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, +0.0);
					gl::end();
					// no "break" intentionally
				case 'D':
				case 'd':
					gl::begin(gl::_line_loop);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.5, +0.0);
					gl::end();
					break;
				case 'E':
				case 'e':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, +0.0);
					gl::end();
					// no "break" intentionally
				case 'C':
				case 'c':
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					break;
				case 'F':
				case 'f':
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::end();
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, +0.0);
					gl::end();
					break;
				case 'G':
				case 'g':
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.0, -1.0);
					gl::vertex2f(+0.5, -0.5);
					gl::vertex2f(+0.5, +0.0);
					gl::vertex2f(+0.0, +0.0);
					gl::end();
					break;
				case 'H':
				case 'h':
					gl::begin(gl::_lines);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, +0.0);
					gl::end();
					break;
				case 'I':
				case 'i':
					gl::begin(gl::_lines);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::vertex2f(+0.0, +1.0);
					gl::vertex2f(+0.0, -1.0);
					gl::end();
					break;
				case 'J':
				case 'j':
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::end();
					break;
				case 'K':
				case 'k':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::end();
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					break;
				case 'L':
				case 'l':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					break;
				case 'M':
				case 'm':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.0, +1.0);
					gl::vertex2f(+0.0, -1.0);
					gl::end();
					break;
				case 'N':
				case 'n':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.0, +1.0);
					gl::vertex2f(+0.0, -1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::end();
					break;
				case 'O':
				case 'o':
					square(	-0.5, +1.0,
							+0.5, -1.0);
					break;
				case 'R':
				case 'r':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					// no "break" intentionally
				case 'P':
				case 'p':
					square(	-0.5, +1.0,
							+0.5, +0.0);
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(-0.5, -1.0);
					gl::end();
					break;
				case 'Q':
				case 'q':
					gl::begin(gl::_line_loop);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.0, -1.0);
					gl::vertex2f(+0.5, +0.0);
					gl::end();
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.0, +0.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					break;
				case 'S':
				case 's':
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.5, +0.5);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, +0.0);
					gl::vertex2f(+0.5, -1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(-0.5, -0.5);
					gl::end();
					break;
				case 'T':
				case 't':
					gl::begin(gl::_lines);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(+0.0, +1.0);
					gl::vertex2f(+0.0, -1.0);
					gl::end();
					break;
				case 'U':
				case 'u':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::end();
					break;
				case 'V':
				case 'v':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.0, -1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::end();
					break;
				case 'W':
				case 'w':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::end();
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.0, +1.0);
					gl::vertex2f(+0.0, -1.0);
					gl::end();
					break;
				case 'X':
				case 'x':
					gl::begin(gl::_lines);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::end();
					break;
				case 'Y':
				case 'y':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, +0.0);
					gl::vertex2f(+0.5, +1.0);
					gl::end();
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.0, +0.0);
					gl::vertex2f(+0.0, -1.0);
					gl::end();
					break;
				case 'Z':
				case 'z':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					break;

				// digit
				case '0':
					square(	-0.5, +1.0,
							+0.5, -1.0);
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, -0.2);
					gl::vertex2f(+0.5, +0.2);
					gl::end();
					break;
				case '1':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.2, +0.5);
					gl::vertex2f(+0.3, +1.0);
					gl::vertex2f(+0.3, -1.0);
					gl::end();
					break;
				case '2':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(+0.5, +0.0);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					break;
				case '3':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::end();
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, +0.0);
					gl::end();
					break;
				case '4':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, +0.0);
					gl::end();
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					break;
				case '5':
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, +0.0);
					gl::vertex2f(+0.5, -1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::end();
					break;
				case '6':
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.0, +1.0);
					gl::vertex2f(-0.5, +0.5);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::vertex2f(+0.5, +0.0);
					gl::vertex2f(-0.5, +0.0);
					gl::end();
					break;
				case '7':
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					break;
				case '8':
					gl::begin(gl::_line_loop);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					break;
				case '9':
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.0, -1.0);
					gl::vertex2f(+0.5, -0.5);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(-0.5, +0.0);
					gl::vertex2f(+0.5, +0.0);
					gl::end();
					break;

				// unknown
				default:
					gl::begin(gl::_line_strip);
					gl::vertex2f(-0.5, +1.0);
					gl::vertex2f(+0.5, -1.0);
					gl::end();
					gl::begin(gl::_line_strip);
					gl::vertex2f(+0.5, +1.0);
					gl::vertex2f(-0.5, -1.0);
					gl::end();
					square(	-0.5, +1.0,
							+0.5, -1.0);
			}
		}
	}
}

